import json
import re
from datetime import datetime
from typing import Dict, Any
from openai import OpenAI
import os

client_cn = OpenAI(
    api_key=os.getenv("OPENAI_API_KEY", "sk-5856dcd20c4e468db0bd53e763bcbd0e"),
    base_url=os.getenv(
        "OPENAI_API_BASE_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1"
    ),
)
client = OpenAI(
    api_key=os.getenv(
        "OPENAI_API_KEY", "sk-XvscnLu7HUR62QtquoqZVHRvrqNdHgvKFeZ3KYnKbqjn8KrU"
    ),
    base_url=os.getenv("OPENAI_API_BASE_URL", "https://api-ai-us.pingpongx.org/v1"),
)

model = "gpt-4.1"

case1 = {
    "dt": "2025-07-01",
    "question": "中行大额存单600-5000，6-8.6，1个月大额存单，",
    "answer": {
        "bank": "中行",
        "biz_type": "网开",
        "end_date": 5000,
        "start_date": "2025-07-06",
        "end_date": "2025-08-06",
        "days": 32,
        "price": None,
        "bonus_type": "按天",
        "total_amt": None,
        "remark": "当前7月，8.6表示8月6日，因此存在跨月，所以累计存放天数32天。补贴单价未提供，默认为None，因此总补贴金额也无法计算，为None",
    },
}

case2 = {
    "dt": "2025-07-05",
    "question": "中行收2.7亿  7一8   万0.5  2000起拆（上午进款）",
    "answer": {
        "bank": "中行",
        "biz_type": "网开",
        "end_date": 27000,
        "start_date": "2025-07-07",
        "end_date": "2025-07-08",
        "days": 2,
        "price": 0.5,
        "bonus_type": "按天",
        "total_amt": 27000,
        "remark": "文本中未明确提及临柜，因此默认为网开；金额'2.7亿'换算为27000万元；当前为7月，时间段'7一8'解析为7日到8日，因此计算7月7日至7月8日；补贴单价'万0.5'提取为0.5",
    },
}

case3 = {
    "dt": "2025-07-02",
    "question": "中行 8-10",
    "answer": {
        "bank": "中行",
        "biz_type": "网开",
        "end_date": None,
        "start_date": "2025-07-08",
        "end_date": "2025-07-10",
        "days": 3,
        "price": None,
        "bonus_type": None,
        "total_amt": None,
        "remark": "invalid",
    },
}


class BankInfoExtractor:
    def __init__(self, api_key=""):
        """
        初始化银行信息抽取器

        Args:
            api_key: OpenAI API密钥
        """
        self.client = client

    def extract_info(self, text: str, current_date: str = None):
        """
        从文本中抽取银行相关信息

        Args:
            text: 输入文本
            current_date: 当前日期，格式为YYYY-MM-DD，如果不提供则使用今天

        Returns:
            包含抽取信息的字典
        """
        if current_date is None:
            current_date = datetime.now().strftime("%Y-%m-%d")

        prompt = self._create_prompt(text, current_date)
        input_text = f"{text}"

        try:
            response = self.client.chat.completions.create(
                model=model,
                messages=[
                    {"role": "system", "content": prompt},
                    {
                        "role": "user",
                        "content": f"当前日期：{case1['dt']}; 输入文本：{case1['question']}",
                    },
                    {
                        "role": "assistant",
                        "content": json.dumps(case1["answer"], ensure_ascii=False),
                    },
                    {
                        "role": "user",
                        "content": f"当前日期：{case2['dt']}; 输入文本：{case2['question']}",
                    },
                    {
                        "role": "assistant",
                        "content": json.dumps(case2["answer"], ensure_ascii=False),
                    },
                    {
                        "role": "user",
                        "content": f"当前日期：{case3['dt']}; 输入文本：{case3['question']}",
                    },
                    {
                        "role": "assistant",
                        "content": json.dumps(case3["answer"], ensure_ascii=False),
                    },
                    {
                        "role": "user",
                        "content": f"当前日期：{current_date}; 输入文本：{input_text}",
                    },
                ],
                temperature=0.01,
                max_tokens=1000,
                response_format={"type": "json_object"},
                # extra_body={"enable_thinking": False},
            )

            result_text = response.choices[0].message.content.strip()
            print(result_text)

            # 尝试解析JSON
            try:
                result = json.loads(result_text)
            except json.JSONDecodeError:
                # 如果直接解析失败，尝试提取JSON部分
                json_match = re.search(r"\{.*\}", result_text, re.DOTALL)
                if json_match:
                    result = json.loads(json_match.group())
                else:
                    raise ValueError("无法解析GPT返回的JSON格式")

            # 后处理和验证
            items = result["items"]
            items_new = []
            for i, item in enumerate(items):
                result = self._post_process(item, current_date)
                items_new.append(result)

            return items_new

        except Exception as e:
            print(f"调用GPT API时出错: {e}")
            return self._create_empty_result()

    def _create_prompt(self, text: str, current_date: str) -> str:
        """创建GPT提示词"""
        return f"""
你是一个专业的金融信息抽取助手，需要从文本中准确抽取银行相关信息。

请从以下文本中抽取银行相关信息，并按照指定格式返回JSON：

当前日期：{current_date}，所有时间请参考当前日期进行推理。

抽取规则：
1. 银行：除了以下银行用2个字概括银行名称（如：工行、建行、邮储等），其余用全称
中国工商银行：工行
中国农业银行 ‌：农行
中国银行 ‌：中行
中国建设银行 ：建行
中国邮政储蓄银行：邮储
‌交通银行‌：交行
‌中信银行‌：中信
‌招商银行‌：招行‌‌
‌平安银行‌：平安‌‌
‌兴业银行‌：兴业
‌广发银行‌：广发
‌中国光大银行‌：光大‌‌
‌浦发银行‌：浦发
‌华夏银行‌：华夏

2. 类型：临柜或网开，如果文本中没有明确提及"临柜"或"临桂"，默认为"网开"
3. 金额：具体金额，一般默认单位是万元，有些如果单位是亿，请进行换算；如果是一个范围，则取较大的那个数字，注意只提取数字；
4. 起止时间段和存放天数，从简单日期格式解析出对应的起止日期，如果跨月需要做相应调整，存放天数等于起止时间差。
    举例说明：
      -案例1：  加入当前是2025-05-01，"4-6"，解析为2025-05-04~2025-05-06，一共3天；
      -案例2： 比如当前是2025-05-01，"2-6.7"，解析为2025-05-06~2025-06-07，一共33天
5. 补贴单价：银行补贴单价，提取数字部分，如"万3"表示3，如果没有则输出None;
6. 补贴类型：默认"按天"，如果文案中提及"总包"、"总"、"总量"则默认为一次性结算，输出："按次"
7. 总补贴金额：根据公式计算
   - 按天：金额 × 天数 × 补贴单价
   - 按次：金额 × 补贴单价
   请计算出最终的值
8、备注：有些字段缺失，默认的填充理由；如果跟金融信息无关，请直接输出“invalid”！有效信息至少需要包含：银行+金额。

请注意如果一段话中包含多条信息，请先对信息做去重处理，然后将信息分条拆分，然后进行解析，注意保持每个都是json。

请严格按照以下JSON格式返回，不要添加任何其他文字：

{{'items':[{{
    "bank": "银行名称，除上述要求的银行用2个字，其余用全称",
    "biz_type": "临柜/网开，不特殊说明是网开",
    "amount": 数字，单位是万,
    "start_date": "YYYY-MM-DD",
    "end_date": "YYYY-MM-DD", 
    "days": 数字，存放天数,
    "price": 数字，万分之几,
    "bonus_type": "按天/按次",
    "total_amt": 数字，取整数,
    "remark": "需要说明的情况，比如有些字段没有给出，或者模棱两可的情况，如果银行和金额有一个包含输出invalid"}}
]
}}
"""

    def _post_process(
        self, result: Dict[str, Any], current_date: str
    ) -> Dict[str, Any]:
        """后处理和验证结果"""
        try:
            # 验证和修正时间
            if result.get("start_date") and result.get("end_date"):
                start_date = datetime.strptime(result["start_date"], "%Y-%m-%d")
                end_date = datetime.strptime(result["end_date"], "%Y-%m-%d")
                days = (end_date - start_date).days
                result["days"] = days

            # 重新计算总补贴金额
            if all(
                key in result for key in ["end_date", "days", "price", "bonus_type"]
            ):
                if result["bonus_type"] == "按次":
                    total_subsidy = result["amount"] * result["price"]
                else:  # 按天
                    total_subsidy = result["amount"] * result["days"] * result["price"]
                result["total_amt"] = total_subsidy

            return result

        except Exception as e:
            print(f"后处理时出错: {e}")
            return result

    def _create_empty_result(self) -> Dict[str, Any]:
        """创建空结果"""
        return [
            {
                "bank": "",
                "biz_type": "网开",
                "end_date": 0,
                "start_date": "",
                "end_date": "",
                "days": 0,
                "price": 0,
                "bonus_type": "按天",
                "total_amt": 0,
            }
        ]


def get_format_info(text):
    print(text)
    extractor = BankInfoExtractor()
    current_date = datetime.now().strftime("%Y-%m-%d")
    result = extractor.extract_info(text, current_date)

    res_json_str = json.dumps(result, ensure_ascii=False, indent=2)
    formatted_text_arr = []
    for item in result:
        res_arr = [str(k) + "@" + str(v) for k, v in item.items()]
        res_info_str = "\n".join(res_arr)
        formatted_text = f"抽取结果：\n{res_info_str}"
        formatted_text_arr.append(formatted_text)
    return result, formatted_text, res_json_str


def main():
    """主函数，演示如何使用"""
    # 请替换为你的OpenAI API密钥
    API_KEY = "your-openai-api-key-here"

    # 创建抽取器实例
    extractor = BankInfoExtractor(API_KEY)

    # 测试案例
    test_cases = [
        "佛山顺德，邮储2000临柜，4-6，万3，时间有限，抓紧、抓紧！",
        "工商银行5000万，网开，7-10号，万2.5总包",
        "建行1000，明天到后天，万4按天计算",
    ]

    # 设置当前日期（用于测试）
    current_date = "2025-07-06"

    for i, text in enumerate(test_cases, 1):
        print(f"\n=== 测试案例 {i} ===")
        print(f"输入文本: {text}")

        result = extractor.extract_info(text, current_date)

        print("抽取结果:")
        print(json.dumps(result, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    txt = "☀中行，600~4600，存单1个月，6-8.7，（31天&综收高&能顺延）"
    #     txt = '中行收2.7亿  7一8   万0.5  2000起拆（上午进款）'
    #     txt = '农行400  6-7  万1'
    #     txt = "中行大额存单600-5000，6-8.6，1个月大额存单，"
    #     txt = "收工行总量 7500万。8号之前完成 价格0.6 不切"
    #     txt = """临柜单 河南邮储需要个人款1000需要查证身份证。万1.1每天    可拆。
    #     7.9号前进8.1出"""
    #     txt = """☀中行，600~4600，存单1个月，6-8.7，（31天&综收高&能顺延）"""
    #     txt = """满三千就是诈骗罪
    # 要去蹲大牢"""
    #     txt = """1 骗子会自己拉群都是那种不需要任何审核的小群
    # 2 小群进入没有门槛，你都不知道什么原因被拉进去了.
    # 3 进群以后他们会把头像微信名称都换掉 ，一批出问题，另一批又留下来了
    # 4 他们会先利用小单子合作，以博取信任，不断地获得跟好友的合作记录，然后伺机收割
    # 5 然后再从小群进入到大群锁定目标客户，甚至他们会互相包装.
    # 6、现已证实多起被骗事件，行骗账号互相拉群换名潜伏（翻群记录互拉可查）.甚至多个行骗账号收款人均为同一人！确凿的团伙作案！希望被骗人联合起来收集证据[抱拳]"""
    #     txt = """自有资金400-500找农行过夜单有的联系， 0.8就出"""
    txt = """0⃣3⃣佛山顺德，邮储2000临柜，4-6，万3，时间有限，抓紧、抓紧！

"""
    txt = """0⃣1⃣收 邮储临柜1200 4---8.3 河南濮阳临柜 能做的来"""
    txt = """收工行定位4-11，额度300W可拆，价格万0.65每天"""
    txt = """河南农村商业银行  300w 25-29 0.3"""
    txt = """中行50，20-21能提前开户来好价

    中行50，20-21能提前开户来好价

    工行日切收15亿，月底前干完，要临桂"""
    txt = "宁波 27-33 "
    result, formatted_text, res_info_str = get_format_info(txt)
    print(formatted_text)
    print(res_info_str)
    print(result)
